//
//  AppDelegate.m
//  iOS-test
//
//  Created by 郭涧川 on 16/6/28.
//  Copyright © 2016年 郭涧川. All rights reserved.
//
#include <stdio.h>
#include <string.h>
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import "AppDelegate.h"
#import "DetailViewController.h"


#include "locketdef.h"
#include "locketcipher.h"
#include "locketaes.h"
#include "locketerrno.h"
#include "lockethttpagent.h"

@interface AppDelegate () <UISplitViewControllerDelegate>

@end

@implementation AppDelegate
CFSocketRef  _socket;

BOOL isOnline;
- (void)createClient

{
    // 创建Socket,无须回调函数
    
    _socket = CFSocketCreate(kCFAllocatorDefault,
                             
                             PF_INET // 指定协议族,如果该参数为0或者负数,则默认为PF_INET
                             
                             // 指定Socket类型,如果协议族为PF_INEF,且该参数为0或负数
                             
                             // 则它会默认为SOCK_STREAM,如果要使用UDP协议,则该参数指定为SOCK_DGRAM
                             
                             , SOCK_STREAM
                             
                             // 指定通信协议.如果前一个参数为SOCK_STREAM,则默认使用TCP协议
                             
                             // 如果前一个参数SOCK_DGRAM,则默认使用UDP协议
                             
                             , IPPROTO_TCP
                             
                             // 该参数指定下一个回调函数所监听的事件类型
                             
                             ,  kCFSocketNoCallBack
                             
                             ,  nil
                             
                             ,  NULL);
    
    if(_socket != nil)
        
    {
        
        // 定义sockaddr_in类型的变量,该变量将作为CFSocket的地址
        
        struct  sockaddr_in  addr4;
        
        memset(&addr4, 0, sizeof(addr4));
        
        addr4.sin_len = sizeof(addr4);
        
        addr4.sin_family = AF_INET;
        
        // 设置连接远程服务器的地址
        
        addr4.sin_addr.s_addr = inet_addr("127.0.0.1");
        
        // 设置连接远程服务器的监听端口
        
        addr4.sin_port = htons(1234);
        
        // 将IPv4的地址转换为CFDataRef
        CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8 *)&addr4, sizeof(addr4));
        
        // 连接远程服务器的Socket,并返回连接结果
        CFSocketError result = CFSocketConnectToAddress (_socket, address, 5);
        // 如果连接远程服务器成功
        
        if(result == kCFSocketSuccess)
            
        {
            
            isOnline = YES;
            
            // 启动新线程来读取服务器响应的数据
            
            [NSThread detachNewThreadSelector:@selector(sendStream)
             
                                     toTarget:self withObject:nil];
            
        }
        
    }
    
}

// 读取接收的数据

- (void)readStream

{
    
    char buffer[2048];
    
    int hasRead;
    
    // 与本机关联的Socket如果已经失效,则返回-1:INVALID_SOCKET
    
    while ((hasRead = (int)recv(CFSocketGetNative(_socket)
                           
                           , buffer, sizeof(buffer), 0)))
        
    {
        
        NSLog(@"%@", [[NSString alloc] initWithBytes:buffer
                      
                                              length:hasRead encoding:NSUTF8StringEncoding]);
        
    }
    
}
- (void)sendStream

{
    
    NSString* stringTosend = @"come from iOS";
    
    const char* data = [stringTosend UTF8String];
    
    send(CFSocketGetNative(_socket), data, strlen(data) +1, 1);
    
}
-  (IBAction)clicked:(id)sender

{
    
    if(isOnline)
        
    {
        
        NSString* stringTosend = @"come from iOS";
        
        const char* data = [stringTosend UTF8String];
        
        send(CFSocketGetNative(_socket), data, strlen(data) +1, 1);
        
    }
    
    else
        
    {
        
        NSLog(@"暂未连接服务器");
        
    }
    
}

- (void)AES_Test
{
    int iErr = ERR_COMMON_SUCCESS;

    /* AES 加密 */
    CIPHER_AES_S stCipherAes;
    memset (&stCipherAes, 0, sizeof (stCipherAes));
    
    stCipherAes.pucInput = (unsigned char*)"hello,world";
    stCipherAes.iInputLen = (int)strlen((char*) stCipherAes.pucInput);
    stCipherAes.iInputEncode = ENCODE_BINARY;
    
    unsigned char szbuffer[1024*2]= {0};
    stCipherAes.iMode = ENCRYPT;
    stCipherAes.iOutputEncode = ENCODE_BASE64;
    stCipherAes.pucOutput = szbuffer;
    
    stCipherAes.pucKey = (unsigned char*)"dGhpcyBpcyBrZXk=";
    stCipherAes.pucIv = (unsigned char*)"dGhpcyBpcyBpdg==";
    
    snprintf(stCipherAes.szAlgoName, sizeof (stCipherAes.szAlgoName), "%s", "AES-128-CFB");
    
    iErr = LOCKET_CIPHER_AESCrypt (&stCipherAes);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("AES encrypt failed, iErr:%d\n", iErr);
        return;
    }
    
    /* AES 解密 */
    stCipherAes.iMode = DECRYPT;
    stCipherAes.pucInput = stCipherAes.pucOutput;
    stCipherAes.iInputLen = stCipherAes.iOutputLen;
    stCipherAes.iInputEncode = ENCODE_BASE64;
    
    // stCipherAes.pucKey = (unsigned char*)"this is key";
    //stCipherAes.pucIv = (unsigned char*)"this is iv";
    
    unsigned char szbuffer2[1024*2]= {0};
    stCipherAes.pucOutput = szbuffer2;
    stCipherAes.iOutputEncode = ENCODE_BINARY;
    iErr = LOCKET_CIPHER_AESCrypt (&stCipherAes);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        printf ("AES decrypt failed");
        return;
    }
    
    printf ("finish\n");
}

- (void)initProxy
{
    int err = LOCKET_HTTPAGENT_Init ((char*)"www.sohu.com", 80);
    if (0 != err)
    {
        NSLog(@"init proxy failed");
    }
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
    UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
    navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
    splitViewController.delegate = self;
    
    
    /* 初始化 */
    LOCKET_CIPHER_Init();
    //[self createClient];
    //[self AES_Test];
    [self initProxy];
    
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

#pragma mark - Split view

- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
    if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]] && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
        // Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
        return YES;
    } else {
        return NO;
    }
}

@end
